#================================================
package MSN3::Util;
#================================================

use strict;
use warnings;

use Switch;

sub checksum { my $o = tell(DATA); seek DATA,0,0; local $/; my $t = unpack("%32C*",<DATA>) % 65535;seek DATA,$o,0; return $t;};

sub convertError
{
  	my $err = shift;
  	my %errlist;

  	$errlist{200} = 'Invalid Syntax';
  	$errlist{201} = 'Invalid parameter';
  	$errlist{204} = 'Invalid contact network';
  	$errlist{205} = 'Invalid user';
  	$errlist{206} = 'Domain name missing';
  	$errlist{207} = 'Already logged in';
  	$errlist{208} = 'Invalid User Name';
  	$errlist{209} = 'Invlaid Friendly Name';
  	$errlist{210} = 'List Full';
  	$errlist{213} = 'Invalid Name Request';
  	$errlist{215} = 'User already on list';
  	$errlist{216} = 'User not on list';
  	$errlist{217} = 'User not online';
  	$errlist{218} = 'Already in that mode';
  	$errlist{219} = 'User is in the opposite list';
  	$errlist{223} = 'Too Many Groups';
  	$errlist{224} = 'Invalid Groups ';
  	$errlist{225} = 'User Not In Group';
  	$errlist{227} = 'Principal not in group';
  	$errlist{228} = 'Group Name already exists';
  	$errlist{229} = 'Group Name too long';
  	$errlist{230} = 'Cannont Remove Group Zero';
  	$errlist{231} = 'Invalid Group';
  	$errlist{240} = 'No Contact In Domain ADL/RML';
  	$errlist{241} = 'ADL/RML commands accept FL(1)/AL(2)/BL(4) not RL(8)/PL(16)';
  	$errlist{280} = 'Switchboard Failed';
  	$errlist{281} = 'Transfer to Switchboard failed';

  	$errlist{300} = 'Required Field Missing';
  	$errlist{301} = 'Too Many Hits to FND';
  	$errlist{302} = 'Not Logged In';

  	$errlist{402} = 'Error accessing contact list';
  	$errlist{403} = 'Error accessing contact list';
  	$errlist{420} = 'Invalid account permissions';

  	$errlist{500} = 'Internal Server Error';
  	$errlist{501} = 'Database Server Error';
  	$errlist{502} = 'Command Disabled';
  	$errlist{509} = 'Ups failure';
  	$errlist{510} = 'File Operation Failed';
  	$errlist{511} = 'Banned';
  	$errlist{520} = 'Memory Allocation Failed';
  	$errlist{540} = 'Challenge Responce Failed';

  	$errlist{600} = 'Server Is Busy';
  	$errlist{601} = 'Server Is Unavailable';
  	$errlist{602} = 'Peer Name Server is Down';
  	$errlist{603} = 'Database Connection Failed';
  	$errlist{604} = 'Server Going Down';
  	$errlist{605} = 'Server Unavailable';

  	$errlist{700} = 'Connection creation failed';
  	$errlist{707} = 'Could Not Create Connection';
  	$errlist{710} = 'Bad CVR Parameter Sent';
  	$errlist{711} = 'Write is Blocking';
  	$errlist{712} = 'Session is Overloaded';
  	$errlist{713} = 'Too Many Active Users';
  	$errlist{714} = 'Too Many Sessions';
  	$errlist{715} = 'Command Not Expected';
  	$errlist{717} = 'Bad Friend File';
  	$errlist{731} = 'Badly Formated CVR';

  	$errlist{800} = 'Friendly Name Change too Rapidly';

  	$errlist{910} = 'Server Too Busy';
  	$errlist{911} = 'Authentication Failed';
  	$errlist{912} = 'Server Too Busy';
  	$errlist{913} = 'Not allowed While Offline';
  	$errlist{914} = 'Server Not Available';
  	$errlist{915} = 'Server Not Available';
  	$errlist{916} = 'Server Not Available';
  	$errlist{917} = 'Authentication Failed';
  	$errlist{918} = 'Server Too Busy';
  	$errlist{919} = 'Server Too Busy';
  	$errlist{920} = 'Not Accepting New Users';
  	$errlist{921} = 'Server Too Busy: User Digest';
  	$errlist{922} = 'Server Too Busy';
  	$errlist{923} = 'Kids Passport Without Parental Consent';
  	$errlist{924} = 'Passport Account Not Verified';
  	$errlist{928} = 'Bad Ticket';
  	$errlist{931} = 'Account Not On Server';
  	$errlist{933} = 'Invalid Circle In ADL';

  	return ( $errlist{$err} || 'unknown error' );
}

sub getCapabilities
{
  	my $cid = shift;
    my $ecid = 0;

    ($cid, $ecid) = split(/:/, $cid, 2);
    $cid = int($cid);
    $ecid = int($ecid);
    my $info = {};

    $info->{Client} = 'MSNC1' if( $cid >= 0x10000000 );
    $info->{Client} = 'MSNC2' if( $cid >= 0x20000000 );
    $info->{Client} = 'MSNC3' if( $cid >= 0x30000000 );
    $info->{Client} = 'MSNC4' if( $cid >= 0x40000000 );
    $info->{Client} = 'MSNC5' if( $cid >= 0x50000000 );
    $info->{Client} = 'MSNC6' if( $cid >= 0x60000000 );
    $info->{Client} = 'MSNC7' if( $cid >= 0x70000000 );
    $info->{Client} = 'MSNC8' if( $cid >= 0x80000000 );
    $info->{Client} = 'MSNC9' if( $cid >= 0x90000000 );
    $info->{Client} = 'MSNC10' if( $cid >= 0xA0000000 );
    $info->{Client} = 'MSNC11' if( $cid >= 0xB0000000 );
    $info->{Client} = 'MSNC12' if( $cid >= 0xC0000000 );
    $info->{Client} = 'MSNC13' if( $cid >= 0xD0000000 );
    $info->{Client} = 'MSNC14' if( $cid >= 0xE0000000 );
    $info->{Client} = 'MSNC15' if( $cid >= 0xF0000000 );

    $info->{WinMobile} = ( ($cid & 0x01) == 0x01 ) ? 1 : 0;
    $info->{ConnectedViaTexas} = ( ($cid & 0x02) == 0x02 ) ? 1 : 0;
    $info->{SupportsGifInk} = ( ($cid & 0x04) == 0x04 ) ? 1 : 0;
    $info->{SupportsIsfInk} = ( ($cid & 0x08) == 0x08 ) ? 1 : 0;
    $info->{WebCamDetected} = ( ($cid & 0x10) == 0x10 ) ? 1 : 0;
    $info->{SupportsChunking} = ( ($cid & 0x20) == 0x20 ) ? 1 : 0;
    $info->{MobileEnabled} = ( ($cid & 0x40) == 0x40 ) ? 1 : 0;
    $info->{WebWatchEnabled} = ( ($cid & 0x80) == 0x80 ) ? 1 : 0;
    $info->{SupportsActivities} = ( ($cid & 0x100) == 0x100 ) ? 1 : 0;
    $info->{OnlineViaWebIM} = ( ($cid & 0x200) == 0x200 ) ? 1 : 0;
    $info->{MobileDevice} = ( ($cid & 0x400) == 0x400 ) ? 1 : 0;
    $info->{ConnectedViaTGW} = ( ($cid & 0x800) == 0x800 ) ? 1 : 0;
    $info->{HasSpace} = ( ($cid & 0x1000) == 0x1000 ) ? 1 : 0;
    $info->{IsMceUser} = ( ($cid & 0x2000) == 0x2000 ) ? 1 : 0;
    $info->{SupportsDirectIM} = ( ($cid & 0x4000) == 0x4000 ) ? 1 : 0;
    $info->{SupportsWinks} = ( ($cid & 0x8000) == 0x8000 ) ? 1 : 0;
    $info->{SupportsSharedSearch} = ( ($cid & 0x10000) == 0x10000 ) ? 1 : 0;
    $info->{IsBot} = ( ($cid & 0x20000) == 0x20000 ) ? 1 : 0;
    $info->{SupportsVoiceIM} = ( ($cid & 0x40000) == 0x40000 ) ? 1 : 0;
    $info->{SupportsSChannel} = ( ($cid & 0x80000) == 0x80000 ) ? 1 : 0;
    $info->{SupportsSipInvite} = ( ($cid & 0x100000) == 0x100000 ) ? 1 : 0;
    $info->{SupportsVideoCall} = ( ($cid & 0x200000) == 0x200000 ) ? 1 : 0;
    $info->{SupportsSDrive} = ( ($cid & 0x400000) == 0x400000 ) ? 1 : 0;
    $info->{SupportsPageModeMessaging} = ( ($cid & 0x800000) == 0x800000 ) ? 1 : 0;
    $info->{HasOneCare} = ( ($cid & 0x1000000) == 0x1000000 ) ? 1 : 0;
    $info->{P2PSupportsTurn} = ( ($cid & 0x2000000) == 0x2000000 ) ? 1 : 0;
    $info->{P2PBootstrapViaUUN} = ( ($cid & 0x4000000) == 0x4000000 ) ? 1 : 0;
    $info->{UsingAlias} = ( ($cid & 0x8000000) == 0x8000000 ) ? 1 : 0;

    $info->{IsSmsOnly} = ( ($ecid & 0x01) == 0x01 ) ? 1 : 0;
    $info->{SupportsVoiceOverMsnp} = ( ($ecid & 0x02) == 0x02 ) ? 1 : 0;
    $info->{SupportsUucpSipStack} = ( ($ecid & 0x04) == 0x04 ) ? 1 : 0;
    $info->{SupportsApplicationMessages} = ( ($ecid & 0x08) == 0x08 ) ? 1 : 0;
    $info->{RTCVideoEnabled} = ( ($ecid & 0x10) == 0x10 ) ? 1 : 0;
    $info->{SupportsPeerToPeerV2} = ( ($ecid & 0x20) == 0x20 ) ? 1 : 0;
    $info->{IsAuthenticatedWebIMUser} = ( ($ecid & 0x40) == 0x40 ) ? 1 : 0;
    $info->{Supports1On1ViaGroup} = ( ($ecid & 0x80) == 0x80 ) ? 1 : 0;
    $info->{SupportsOfflineIM} = ( ($ecid & 0x100) == 0x100 ) ? 1 : 0;
    $info->{SharingVideoSupport} = ( ($ecid & 0x200) == 0x200 ) ? 1 : 0;
    $info->{SupportsNudges} = ( ($ecid & 0x400) == 0x400 ) ? 1 : 0;
    $info->{CircleVoiceIMEnabled} = ( ($ecid & 0x800) == 0x800 ) ? 1 : 0;
    $info->{SharingEnabled} = ( ($ecid & 0x1000) == 0x1000 ) ? 1 : 0;
    $info->{MobileSuspendIMFanoutDisable} = ( ($ecid & 0x2000) == 0x2000 ) ? 1 : 0;
    $info->{UNKNOWN_0x4000} = ( ($ecid & 0x4000) == 0x4000 ) ? 1 : 0;
    $info->{SupportsPeerToPeerMixerRelay} = ( ($ecid & 0x8000) == 0x8000 ) ? 1 : 0;
    $info->{UNKNOWN_0x10000} = ( ($ecid & 0x10000) == 0x10000 ) ? 1 : 0;
    $info->{ConvWindowFileTransfer} = ( ($ecid & 0x20000) == 0x20000 ) ? 1 : 0;
    $info->{UNKNOWN_0x40000} = ( ($ecid & 0x40000) == 0x40000 ) ? 1 : 0;
    $info->{SupportsPeerToPeerEnveloping} = ( ($ecid & 0x80000) == 0x80000 ) ? 1 : 0;
    $info->{UNKNOWN_0x100000} = ( ($ecid & 0x100000) == 0x100000 ) ? 1 : 0;
    $info->{UNKNOWN_0x200000} = ( ($ecid & 0x200000) == 0x200000 ) ? 1 : 0;
    $info->{YahooIMDisabled} = ( ($ecid & 0x400000) == 0x400000 ) ? 1 : 0;
    $info->{SIPTunnelVersion2} = ( ($ecid & 0x800000) == 0x800000 ) ? 1 : 0;
    $info->{VoiceClipSupportsWMAFormat} = ( ($ecid & 0x1000000) == 0x1000000 ) ? 1 : 0;
    $info->{VoiceClipSupportsCircleIM} = ( ($ecid & 0x2000000) == 0x2000000 ) ? 1 : 0;
    $info->{SupportsSocialNewsObjectType} = ( ($ecid & 0x4000000) == 0x4000000 ) ? 1 : 0;
    $info->{UNKNOWN_0x8000000} = ( ($ecid & 0x8000000) == 0x8000000 ) ? 1 : 0;
    $info->{UNKNOWN_0x10000000} = ( ($ecid & 0x10000000) == 0x10000000 ) ? 1 : 0;
    $info->{FTURNCapable} = ( ($ecid & 0x20000000) == 0x20000000 ) ? 1 : 0;
    $info->{UNKNOWN_0x40000000} = ( ($ecid & 0x40000000) == 0x40000000 ) ? 1 : 0;
    $info->{SupportsMultiPartyIM} = ( ($ecid & 0x80000000) == 0x80000000 ) ? 1 : 0;

  	return $info;
}

sub setCapabilities
{
  	my $info = shift;
    my $type = shift || undef;
    my $client = shift || 1;

    my $cid = 0;
    my $ecid = 0;

    if($client)
    {
        switch($info->{Client})
        {
            case "MSNC1"  { $cid += 0x10000000; }
            case "MSNC2"  { $cid += 0x20000000; }
            case "MSNC3"  { $cid += 0x30000000; }
            case "MSNC4"  { $cid += 0x40000000; }
            case "MSNC5"  { $cid += 0x50000000; }
            case "MSNC6"  { $cid += 0x60000000; }
            case "MSNC7"  { $cid += 0x70000000; }
            case "MSNC8"  { $cid += 0x80000000; }
            case "MSNC9"  { $cid += 0x90000000; }
            case "MSNC10" { $cid += 0xA0000000; }
            case "MSNC11" { $cid += 0xB0000000; }
            case "MSNC12" { $cid += 0xC0000000; }
            case "MSNC13" { $cid += 0xD0000000; }
        }
    }

  	$cid +=      0x01 if( $info->{WinMobile} && (!defined $type || $info->{WinMobile} eq $type) );
  	$cid +=      0x02 if( $info->{ConnectedViaTexas} && (!defined $type || $info->{ConnectedViaTexas} eq $type) );
  	$cid +=      0x04 if( $info->{SupportsGifInk} && (!defined $type || $info->{SupportsGifInk} eq $type) );
  	$cid +=      0x08 if( $info->{SupportsIsfInk} && (!defined $type || $info->{SupportsIsfInk} eq $type) );
  	$cid +=      0x10 if( $info->{WebCamDetected} && (!defined $type || $info->{WebCamDetected} eq $type) );
  	$cid +=      0x20 if( $info->{SupportsChunking} && (!defined $type || $info->{SupportsChunking} eq $type) );
  	$cid +=      0x40 if( $info->{MobileEnabled} && (!defined $type || $info->{MobileEnabled} eq $type) );
  	$cid +=      0x80 if( $info->{WebWatchEnabled} && (!defined $type || $info->{WebWatchEnabled} eq $type) );
  	$cid +=     0x100 if( $info->{SupportsActivities} && (!defined $type || $info->{SupportsActivities} eq $type) );
  	$cid +=     0x200 if( $info->{OnlineViaWebIM} && (!defined $type || $info->{OnlineViaWebIM} eq $type) );
  	$cid +=     0x400 if( $info->{MobileDevice} && (!defined $type || $info->{MobileDevice} eq $type) );
  	$cid +=     0x800 if( $info->{ConnectedViaTGW} && (!defined $type || $info->{ConnectedViaTGW} eq $type) );
  	$cid +=    0x1000 if( $info->{HasSpace} && (!defined $type || $info->{HasSpace} eq $type) );
  	$cid +=    0x2000 if( $info->{IsMceUser} && (!defined $type || $info->{IsMceUser} eq $type) );
  	$cid +=    0x4000 if( $info->{SupportsDirectIM} && (!defined $type || $info->{SupportsDirectIM} eq $type) );
  	$cid +=    0x8000 if( $info->{SupportsWinks} && (!defined $type || $info->{SupportsWinks} eq $type) );
  	$cid +=   0x10000 if( $info->{SupportsSharedSearch} && (!defined $type || $info->{SupportsSharedSearch} eq $type) );
  	$cid +=   0x20000 if( $info->{IsBot} && (!defined $type || $info->{IsBot} eq $type) );
  	$cid +=   0x40000 if( $info->{SupportsVoiceIM} && (!defined $type || $info->{SupportsVoiceIM} eq $type) );
  	$cid +=   0x80000 if( $info->{SupportsSChannel} && (!defined $type || $info->{SupportsSChannel} eq $type) );
  	$cid +=  0x100000 if( $info->{SupportsSipInvite} && (!defined $type || $info->{SupportsSipInvite} eq $type) );
  	$cid +=  0x200000 if( $info->{SupportsVideoCall} && (!defined $type || $info->{SupportsVideoCall} eq $type) );
  	$cid +=  0x400000 if( $info->{SupportsSDrive} && (!defined $type || $info->{SupportsSDrive} eq $type) );
  	$cid +=  0x800000 if( $info->{SupportsPageModeMessaging} && (!defined $type || $info->{SupportsPageModeMessaging} eq $type) );
  	$cid += 0x1000000 if( $info->{HasOneCare} && (!defined $type || $info->{HasOneCare} eq $type) );
  	$cid += 0x2000000 if( $info->{P2PSupportsTurn} && (!defined $type || $info->{P2PSupportsTurn} eq $type) );
  	$cid += 0x4000000 if( $info->{P2PBootstrapViaUUN} && (!defined $type || $info->{P2PBootstrapViaUUN} eq $type) );
  	$cid += 0x8000000 if( $info->{UsingAlias} && (!defined $type || $info->{UsingAlias} eq $type) );

  	$ecid +=       0x01 if( $info->{IsSmsOnly} && (!defined $type || $info->{IsSmsOnly} eq $type) );
  	$ecid +=       0x02 if( $info->{SupportsVoiceOverMsnp} && (!defined $type || $info->{SupportsVoiceOverMsnp} eq $type) );
  	$ecid +=       0x04 if( $info->{SupportsUucpSipStack} && (!defined $type || $info->{SupportsUucpSipStack} eq $type) );
  	$ecid +=       0x08 if( $info->{SupportsApplicationMessages} && (!defined $type || $info->{SupportsApplicationMessages} eq $type) );
  	$ecid +=       0x10 if( $info->{RTCVideoEnabled} && (!defined $type || $info->{RTCVideoEnabled} eq $type) );
  	$ecid +=       0x20 if( $info->{SupportsPeerToPeerV2} && (!defined $type || $info->{SupportsPeerToPeerV2} eq $type) );
  	$ecid +=       0x40 if( $info->{IsAuthenticatedWebIMUser} && (!defined $type || $info->{IsAuthenticatedWebIMUser} eq $type) );
  	$ecid +=       0x80 if( $info->{Supports1On1ViaGroup} && (!defined $type || $info->{Supports1On1ViaGroup} eq $type) );
  	$ecid +=      0x100 if( $info->{SupportsOfflineIM} && (!defined $type || $info->{SupportsOfflineIM} eq $type) );
  	$ecid +=      0x200 if( $info->{SharingVideoSupport} && (!defined $type || $info->{SharingVideoSupport} eq $type) );
  	$ecid +=      0x400 if( $info->{SupportsNudges} && (!defined $type || $info->{SupportsNudges} eq $type) );
  	$ecid +=      0x800 if( $info->{CircleVoiceIMEnabled} && (!defined $type || $info->{CircleVoiceIMEnabled} eq $type) );
  	$ecid +=     0x1000 if( $info->{SharingEnabled} && (!defined $type || $info->{SharingEnabled} eq $type) );
  	$ecid +=     0x2000 if( $info->{MobileSuspendIMFanoutDisable} && (!defined $type || $info->{MobileSuspendIMFanoutDisable} eq $type) );
  	$ecid +=     0x4000 if( $info->{UNKNOWN_0x4000} && (!defined $type || $info->{UNKNOWN_0x4000} eq $type) );
  	$ecid +=     0x8000 if( $info->{SupportsPeerToPeerMixerRelay} && (!defined $type || $info->{SupportsPeerToPeerMixerRelay} eq $type) );
  	$ecid +=    0x10000 if( $info->{UNKNOWN_0x10000} && (!defined $type || $info->{UNKNOWN_0x10000} eq $type) );
  	$ecid +=    0x20000 if( $info->{ConvWindowFileTransfer} && (!defined $type || $info->{ConvWindowFileTransfer} eq $type) );
  	$ecid +=    0x40000 if( $info->{VideoCallSupports16x9} && (!defined $type || $info->{VideoCallSupports16x9} eq $type) );
  	$ecid +=    0x80000 if( $info->{SupportsPeerToPeerEnveloping} && (!defined $type || $info->{SupportsPeerToPeerEnveloping} eq $type) );
  	$ecid +=   0x100000 if( $info->{UNKNOWN_0x100000} && (!defined $type || $info->{UNKNOWN_0x100000} eq $type) );
  	$ecid +=   0x200000 if( $info->{UNKNOWN_0x200000} && (!defined $type || $info->{UNKNOWN_0x200000} eq $type) );
  	$ecid +=   0x400000 if( $info->{YahooIMDisabled} && (!defined $type || $info->{YahooIMDisabled} eq $type) );
  	$ecid +=   0x800000 if( $info->{SIPTunnelVersion2} && (!defined $type || $info->{SIPTunnelVersion2} eq $type) );
  	$ecid +=  0x1000000 if( $info->{VoiceClipSupportsWMAFormat} && (!defined $type || $info->{VoiceClipSupportsWMAFormat} eq $type) );
  	$ecid +=  0x2000000 if( $info->{VoiceClipSupportsCircleIM} && (!defined $type || $info->{VoiceClipSupportsCircleIM} eq $type) );
  	$ecid +=  0x4000000 if( $info->{SupportsSocialNewsObjectTypes} && (!defined $type || $info->{SupportsSocialNewsObjectTypes} eq $type) );
  	$ecid +=  0x8000000 if( $info->{UNKNOWN_0x8000000} && (!defined $type || $info->{UNKNOWN_0x8000000} eq $type) );
  	$ecid += 0x10000000 if( $info->{UNKNOWN_0x10000000} && (!defined $type || $info->{UNKNOWN_0x10000000} eq $type) );
  	$ecid += 0x20000000 if( $info->{FTURNCapable} && (!defined $type || $info->{FTURNCapable} eq $type) );
  	$ecid += 0x40000000 if( $info->{UNKNOWN_0x40000000} && (!defined $type || $info->{UNKNOWN_0x40000000} eq $type) );
  	$ecid += 0x80000000 if( $info->{SupportsMultiPartyIM} && (!defined $type || $info->{SupportsMultiPartyIM} eq $type) );

  	return $cid .':'. $ecid;
}

return 1;
__DATA__